package com.sparrow.common.aoi;

import com.sparrow.common.aoi.domain.AOIEntity;
import com.sparrow.common.aoi.domain.Area;
import com.sparrow.common.aoi.domain.MapData;
import com.sparrow.common.aoi.impl.ninegrid.AOIMap;
import com.sparrow.common.aoi.listener.AOIListener;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

import static com.sparrow.common.aoi.util.MapUtil.AREA_HEIGHT;
import static com.sparrow.common.aoi.util.MapUtil.AREA_WIDTH;


public class AoiPanel extends JPanel {
    private static final int GRID_PIX = 20;
    private final MapData mapData;
    private List<TestAOIEntity> entities = new ArrayList<>();
    private TestAOIEntity selectedEntity = null;
    private JScrollPane scrollPane;

    private Point mousePressPoint = null;

    private static AtomicLong uuidGenerator = new AtomicLong(0);
    private AOISystem aoiSystem;
    private AOIMap map;
    private AOIListener listener;

    private final Map<Long, Long> highlightMap = new ConcurrentHashMap<>();
    private int[][] gridData;
    private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);

    public AoiPanel(int width, int height, AbstractAOISystem aoiSystem) {
        int gridRow = height / GRID_PIX;
        int gridCol = width / GRID_PIX;
        gridData = new int[gridRow][gridCol];
        for (int y = 0; y < gridRow; y++) {
            for (int x = 0; x < gridCol; x++) {
                gridData[y][x] = 0;
            }
        }
        int h = gridData.length;
        int w = gridData[0].length;
        this.mapData = MapData.create(w, h);

        this.map = new AOIMap() {

            @Override
            public MapData getMapData() {
                return mapData;
            }

            @Override
            public Map<Integer, Area> getAreaMap() {
                return Collections.emptyMap();
            }

            @Override
            public Area getArea(int areaId) {
                return null;
            }
        };

        setBackground(Color.WHITE);
        setPreferredSize(new Dimension(width, height)); // 大地图
        setFocusable(true);
        this.aoiSystem = aoiSystem;
        // 注册一个简单的监听器，模拟广播
        listener = new AOIListener<MapData>() {
            @Override
            public void onEntityEnterView(MapData mapData, AOIEntity self, AOIEntity target) {
                System.out.println("Entity " + target + " 进入 " + self.getAOIId() + " 视野");
                highlightEntity(self.getAOIId());
            }

            @Override
            public void onEntityLeaveView(MapData mapData, AOIEntity self, AOIEntity target) {
                System.out.println("Entity " + target + " 离开 " + self.getAOIId() + " 视野");
                highlightEntity(self.getAOIId());
            }

            @Override
            public void onEntityPositionChange(MapData mapData, AOIEntity self, AOIEntity target) {
                System.out.println(self + " 看到 Entity " + target.getAOIId() + " 移动了");
                highlightEntity(self.getAOIId());
            }
        };
        // 将监听器注册到 NineGridAOI
        aoiSystem.addListener(listener);
        // 添加实体 & 选中实体
        addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                mousePressPoint = e.getPoint();

                requestFocusInWindow();

                selectedEntity = null;
                int x = e.getX() / GRID_PIX;
                int y = e.getY() / GRID_PIX;
                for (TestAOIEntity ent : entities) {
                    if (ent.x == x && ent.y == y) {
                        selectedEntity = ent;
                        break;
                    }
                }

                if (selectedEntity == null) {
                    TestAOIEntity entity = new TestAOIEntity(uuidGenerator.incrementAndGet(), x, y);
                    entities.add(entity);
                    aoiSystem.addAOIEntity(map, entity, entity.getAOIX(), entity.getAOIY());
                }

                repaint();
            }
        });

        // 键盘控制实体移动
        addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                if (selectedEntity == null) {
                    return;
                }

                int step = 1;
                int x = selectedEntity.getAOIX();
                int y = selectedEntity.getAOIY();
                switch (e.getKeyCode()) {
                    case KeyEvent.VK_UP: y -= step; break;
                    case KeyEvent.VK_DOWN: y += step; break;
                    case KeyEvent.VK_LEFT: x -= step; break;
                    case KeyEvent.VK_RIGHT: x += step; break;
                }

                aoiSystem.updateAOIEntityPosition(map, selectedEntity, x, y);
                repaint();
            }
        });
    }

    private void highlightEntity(long id) {
        highlightMap.put(id, System.currentTimeMillis());
        repaint();
        // 200ms 后移除
        executor.schedule(() -> {
            highlightMap.remove(id);
            repaint();
        }, 300, TimeUnit.MILLISECONDS);
    }

    public void setScrollPane(JScrollPane scrollPane) {
        this.scrollPane = scrollPane;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        //画格子地图
        int rows = gridData.length;
        int cols = gridData[0].length;
        // 画横线
        for (int y = 0; y <= rows; y++) {
            g.drawLine(0, y * GRID_PIX, cols * GRID_PIX, y * GRID_PIX);
        }
        // 画竖线
        for (int x = 0; x <= cols; x++) {
            g.drawLine(x * GRID_PIX, 0, x * GRID_PIX, rows * GRID_PIX);
        }
        //画区域
        int areaWidth = (mapData.getWidth() + AREA_WIDTH - 1) / AREA_WIDTH;
        int areaHeight = (mapData.getHeight() + AREA_HEIGHT - 1) / AREA_HEIGHT;
        g.setColor(new Color(85, 0, 255, 211)); // 半透明黄色

        // 画横线
        for (int y = 0; y <= areaWidth; y++) {
            g.drawLine(0, y * GRID_PIX * AREA_WIDTH, cols * GRID_PIX * AREA_WIDTH, y * GRID_PIX * AREA_WIDTH);
        }
        // 画竖线
        for (int x = 0; x <= areaHeight; x++) {
            g.drawLine(x * GRID_PIX * AREA_WIDTH, 0, x * GRID_PIX * AREA_WIDTH, rows * GRID_PIX * AREA_WIDTH);
        }

        for (TestAOIEntity e : entities) {
            if (e == selectedEntity) {
                g.setColor(Color.RED);
            } else if (highlightMap.containsKey(e.id)) {
                g.setColor(Color.GREEN); // 高亮
            } else {
                g.setColor(Color.BLUE);
            }
            g.fillOval(e.x * GRID_PIX, e.y * GRID_PIX, GRID_PIX, GRID_PIX);
            g.drawString(String.format("id=%d (%d,%d)", e.id, e.x, e.y), e.x * GRID_PIX + 6, e.y * GRID_PIX - 6);
        }
    }

}

